package guda.mrpc.core.transport.tcp;

import guda.mrpc.core.RpcResponse;
import guda.mrpc.core.api.Request;
import guda.mrpc.core.client.RpcFuture;
import guda.mrpc.core.transport.ClientHandler;
import guda.mrpc.core.transport.Hearbeat;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by well on 17/5/23.
 */
public class TcpClientHandler extends ClientHandler<Object> {

    private static final Logger log = LoggerFactory.getLogger(TcpClientHandler.class);

    public RpcFuture sendRequest(Request request) {
        RpcFuture rpcFuture = new RpcFuture(request);
        mapCallBack.put(request.getRequestId(), rpcFuture);
        if (log.isDebugEnabled()) {
            log.debug("request: {}", request);
        }
        channel.writeAndFlush(request);
        return rpcFuture;
    }


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if(msg instanceof RpcResponse){
            RpcResponse rpcResponse = (RpcResponse)msg;
            String messageId = rpcResponse.getRequestId();
            RpcFuture rpcFuture = mapCallBack.get(messageId);
            if (rpcFuture != null) {
                mapCallBack.remove(messageId);
                rpcFuture.done(rpcResponse);
            }
        }
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE){
                ctx.writeAndFlush(Hearbeat.heartbeatContent()).addListener(
                        ChannelFutureListener.CLOSE_ON_FAILURE);
            }
        }else{
            super.userEventTriggered(ctx, evt);
        }
    }
}
